package com.syh.jn.scm.service.impl.supplier.stock;

import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.driver.entity.logistics.DriverLogisticsBill;
import com.syh.jn.scm.domain.driver.event.DriverLogisticsBillEvent;
import com.syh.jn.scm.domain.operation.entity.supplier.OperaSupplier;
import com.syh.jn.scm.domain.operation.event.supplier.OperaSupplierEvent;
import com.syh.jn.scm.domain.supplier.entity.logistics.LogisticsBill;
import com.syh.jn.scm.domain.supplier.entity.stock.*;
import com.syh.jn.scm.domain.supplier.event.*;
import com.syh.jn.scm.domain.supplier.repository.logistics.LogisticsBillRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockRecordReadRepository;
import com.syh.jn.scm.domain.supplier.repository.stock.StockRecordRepository;
import com.syh.jn.scm.dto.supplier.stock.StockRecordItemVo;
import com.syh.jn.scm.dto.supplier.stock.StockRecordVo;
import com.syh.jn.scm.service.api.supplier.logistics.enums.LogisticsBillEnums;
import com.syh.jn.scm.service.api.supplier.stock.StockRecordService;
import com.syh.jn.scm.service.api.supplier.stock.enums.StockGoodsRecordEnums;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * 出入库记录
 */
@Service
@Transactional
public class StockRecordServiceImpl extends AbstractServiceImpl<Object, Object, StockRecordVo, StockRecord, Long> implements StockRecordService {
  @Autowired
  private StockRecordRepository stockRecordRepository;
  @Resource(name = "stockRecordReadRepositoryMbImpl")
  private StockRecordReadRepository stockRecordReadRepositoryMbImpl;
  @Autowired
  private LogisticsBillRepository logisticsBillRepository;

  @Override
  protected AggregateRepository<StockRecord, Long> getAggregateRepository() {
    return null;//TODO 继承AbstractServiceImpl类是为了抛出事件
  }

  @Override
  public void repairLogisticsBillEmptyDepot() {
    stockRecordRepository.repairLogisticsBillEmptyDepot();
  }

  @Override
  public void generateStockRecordAtNull() {
    stockRecordRepository.generateStockRecordAtNull();
  }

  @Override
  public StockRecordVo getById(Long id) {
    StockRecordVo stockRecordVo = stockRecordReadRepositoryMbImpl.getById(id);
    //获取出入库记录项
    List<StockRecordItemVo> stockRecordItemsVo = stockRecordReadRepositoryMbImpl.findStockRecordItemsByStockRecordId(stockRecordVo.getId());
    stockRecordVo.setItemsVo(stockRecordItemsVo);

    return stockRecordVo;
  }

  @Override
  public int findStockRecordItemCount(Wrapper wrapper) {
    return stockRecordReadRepositoryMbImpl.findStockRecordItemListPageCount(wrapper);
  }

  @Override
  public List<StockRecordItemVo> findStockRecordItemListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return stockRecordReadRepositoryMbImpl.findStockRecordItemListPage(wrapper, startRow, count);
  }

  @Override
  public boolean contains(Long id) {
    return stockRecordRepository.contains(id);
  }

  @Override
  public List<StockRecordVo> findList(Wrapper wrapper) {
    return stockRecordReadRepositoryMbImpl.getList(wrapper);
  }

  @Override
  public List<StockRecordVo> findListPage(Wrapper wrapper, Integer startRow, Integer count) {
    return stockRecordReadRepositoryMbImpl.findListPage(wrapper, startRow, count);
  }

  @Override
  public StockRecordVo getOne(Wrapper wrapper) {
    return stockRecordReadRepositoryMbImpl.getOne(wrapper);
  }

  @Override
  public int getCount(Wrapper wrapper) {
    return stockRecordReadRepositoryMbImpl.getCount(wrapper);
  }

  /**
   * 监听物流订单发货（插入库存记录）
   *
   * @param bill
   */
  @DomainEventHandle({LogisticsBillEvent.LOGISTICS_BILL_DELIVERY})
  protected void handleLogisticsBillDeliveryEvent(LogisticsBill bill) {
    if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())) {
      StockRecord stockRecord = new StockRecord();
      stockRecord.delivery(bill);
      stockRecordRepository.add(stockRecord);
      super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
    }
  }

  /**
   * 监听司机物流订单发货（插入库存记录）
   *
   * @param driverLogisticsBillill
   */
  @DomainEventHandle({DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_DELIVERY})
  protected void handleDriverLogisticsBillDeliveryEvent(DriverLogisticsBill driverLogisticsBillill) {
    LogisticsBill bill = logisticsBillRepository.getById(driverLogisticsBillill.getId());
    this.handleLogisticsBillDeliveryEvent(bill);
  }

  /**
   * 监听物流订单收货（插入库存记录）
   *
   * @param bill
   */
  @DomainEventHandle({LogisticsBillEvent.LOGISTICS_BILL_COLLECTED})
  protected void handleLogisticsBillCollectedEvent(LogisticsBill bill) {
    if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.PURCHASE.getStatus())) {
      StockRecord stockRecord = new StockRecord();
      stockRecord.collect(bill);
      stockRecordRepository.add(stockRecord);
      super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
    }
  }

  /**
   * 监听司机物流订单收货（插入库存记录）
   *
   * @param driverLogisticsBillill
   */
  @DomainEventHandle({DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_COLLECTED})
  protected void handleDriverLogisticsBillCollectedEvent(DriverLogisticsBill driverLogisticsBillill) {
    LogisticsBill bill = logisticsBillRepository.getById(driverLogisticsBillill.getId());
    this.handleLogisticsBillCollectedEvent(bill);
  }

  /**
   * 监听物流订单修改（调整库存）
   *
   * @param oldBill 未修改前的物流单
   * @param bill    修改后的物流单
   */
  @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_UPDATED)
  protected void handleLogisticsBillUpdatedEvent(LogisticsBill oldBill, LogisticsBill bill) {
    //暂不监听修改事件
//    StockRecord stockRecord = StockRecord.update(bill);
//    stockRecordRepository.update(stockRecord);
  }

  /**
   * 监听物流订单取消发货（减去库存）
   *
   * @param bill
   */
  @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_CANCELLED)
  protected void handleLogisticsBillCancelledEvent(LogisticsBill bill,LogisticsBill oldBill) {
    if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_PURCHASE.getStatus())) {
      StockRecord stockRecord = new StockRecord();
      stockRecord.cancel(oldBill);
      stockRecordRepository.add(stockRecord);
      super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
    }
  }

  /**
   * 监听物流订单取消签收（减去库存）
   *
   * @param bill
   */
  @DomainEventHandle(LogisticsBillEvent.LOGISTICS_BILL_UN_RECEIVED)
  protected void handleLogisticsBillUnReceivedEvent(LogisticsBill bill,LogisticsBill oldBill) {
    if (bill.getOrderType().equals(LogisticsBillEnums.OrderType.RETURN_SALE.getStatus())
            || bill.getOrderType().equals(LogisticsBillEnums.OrderType.PURCHASE.getStatus())) {
      StockRecord stockRecord = new StockRecord();
      stockRecord.cancelReceipt(oldBill);
      stockRecordRepository.add(stockRecord);
      super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
    }
  }

  /**
   * 消费者：获取报损单状态信息
   *
   * @param loss
   */
  @DomainEventHandle({StockLossEvent.STOCK_LOSS_CONFIRM_STATUS, StockLossEvent.STOCK_LOSS_UN_STATUS})
  protected void handleStockLossEnabledDestroyEvent(StockLoss loss) {
    ExtAssert.notNull(loss, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockLossRecord(loss);
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }

  /**
   * 消费者：获取报溢单状态信息
   *
   * @param spill
   */
  @DomainEventHandle({StockSpillEvent.STOCK_SPILL_CONFIRM_STATUS, StockSpillEvent.STOCK_SPILL_UN_CONFIRM_STATUS})
  protected void handleStockSpillDestroyEvent(StockSpill spill) {
    ExtAssert.notNull(spill, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockSpillRecord(spill);
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }

  /**
   * 消费者：监听其他入库单确认
   * @param stockOtherInBill
   */
  @DomainEventHandle({StockOtherInBillEvent.STOCK_OTHER_IN_BILL_CONFIRM_STATUS})
  protected void handleStockOhterInBillConfirm(StockOtherInBill stockOtherInBill) {
    ExtAssert.notNull(stockOtherInBill, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockOtherInBill(stockOtherInBill,StockGoodsRecordEnums.DataType.NORMAL.getStatus());
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }

  /**
   * 消费者：监听其他入库单取消确认
   * @param stockOtherInBill
   * @param oldBill
   */
  @DomainEventHandle(StockOtherInBillEvent.STOCK_OTHER_IN_BILL_CANCEL_CONFIRM_STATUS)
  protected void handleStockOhterInBillCancelConfirm(StockOtherInBill stockOtherInBill,StockOtherInBill oldBill) {
    ExtAssert.notNull(stockOtherInBill, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockOtherInBill(oldBill,StockGoodsRecordEnums.DataType.ROLL_BACK.getStatus());
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }


  /**
   * 消费者：监听其他出库单确认
   * @param stockOtherOutBill
   */
  @DomainEventHandle(StockOtherOutBillEvent.STOCK_OTHER_OUT_BILL_CONFIRM_STATUS)
  protected void handleStockOhterOutBillConfirm(StockOtherOutBill stockOtherOutBill) {
    ExtAssert.notNull(stockOtherOutBill, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockOtherOutBill(stockOtherOutBill,StockGoodsRecordEnums.DataType.NORMAL.getStatus());
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }

  /**
   * 消费者：监听其他出库单取消确认
   * @param stockOtherOutBill
   * @param oldBill
   */
  @DomainEventHandle({StockOtherOutBillEvent.STOCK_OTHER_OUT_BILL_CANCEL_CONFIRM_STATUS})
  protected void handleStockOhterOutBilldCancelConfirm(StockOtherOutBill stockOtherOutBill,StockOtherOutBill oldBill) {
    ExtAssert.notNull(stockOtherOutBill, "对象为空");
    StockRecord stockRecord = new StockRecord();
    stockRecord.saveStockOtherOutBill(oldBill, StockGoodsRecordEnums.DataType.ROLL_BACK.getStatus());
    stockRecordRepository.add(stockRecord);
    super.publicEvent(StockRecordEvent.bulidStockRecordCreated(new Object[]{stockRecord}));
  }

  /**
   * 消费者：监听服务商反开账（删除所有该服务商的出入库记录）
   */
  @DomainEventHandle(OperaSupplierEvent.SUPPLIER_REVERSAL_ACCOUNT)
  protected void handleSupplierReversalAccount(OperaSupplier supplier) {
    this.stockRecordRepository.deleteByBusinessEntityId(supplier.getId());
  }
}
